#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int M=1005;
const int INF=0x3f3f3f3f;
struct Edge{
    //边的起点，终点，容量，流量
    int from,to,cap,flow;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
int n,m;
//保存边 编号从0开始搜索
vector<Edge> edges;
//G[i]保存以i为起点的边的编号，包括反向边
vector<int> G[M];
//记录源点到当前点还有多少流量可用
int a[M];
//记录到达该点的前一条边的编号
int p[M];
void init(){
    for(int i=0;i<M;i++){
        G[i].clear();
    }
    edges.clear();
}
void addEdge(int from,int to,int cap){
    edges.push_back(Edge(from,to,cap,0));
    //加入反向边（没有容量）
    edges.push_back(Edge(to,from,0,0));
    //获取加入前面两条边后的边数（编号）
    m=edges.size();
    //m-2就是先加入的边，即正向边编号，m-1即为反向边编号
    //正向边和反向边编号刚好是^1的关系
    G[from].push_back(m-2);
    G[to].push_back(m-1);
}
int maxFlow(int s,int t){
    int flow=0;
    //bfs不断寻找增广路
    while(true){
        memset(a,0,sizeof(a));
        queue<int> q;
        q.push(s);
        //源点初始化
        a[s]=INF;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            //遍历x出发的所有边，包括反向边
            for(int i=0;i<G[x].size();i++){
                Edge &e=edges[G[x][i]];
                //...    边的容量大于边的当前流量
                if(!a[e.to] && e.cap > e.flow){
                    //记录前驱
                    p[e.to]=G[x][i];
                    //到该店的可用流量等于到上一点的可用流量和这一条边容量流量差的最小值
                    a[e.to]=min(a[x],e.cap-e.flow);
                    //继续搜索
                    q.push(e.to);
                }
            }
            //找到增广路，即到汇点有可用流量
            if(a[t]){
                break;
            }
        }
        //找不到增广路，当前即为最大流
        if(!a[t]){
            break;
        }
        //每一轮bfs结束后，将路径上所有正向边的流量加上delta，反向边的流量减去delta
        for(int u=t;u!=s;u=edges[p[u]].from){
            edges[p[u]].flow+=a[t];
            edges[p[u]^1].flow-=a[t];
        }
        //这里a[t]可能有正负，只要非零都能走到这里
        flow+=a[t];
    }
    return flow;
}
int main(void){
    //freopen("data.txt","r",stdin);
    init();
    int N,F,D;
    scanf("%d%d%d",&N,&F,&D);
    n=N*2+F+D+2;
    for(int i=2;i<=F+1;i++){
        addEdge(1,i,1);
    }
    for(int i=F+2*N+2;i<n;i++){
        addEdge(i,n,1);
    }
    int k1,k2,t;
    for(int i=1;i<=N;i++){
        scanf("%d%d",&k1,&k2);
        while(k1--){
            scanf("%d",&t);
            addEdge(t+1,1+F+i,1);
        }
        while(k2--){
            scanf("%d",&t);
            addEdge(1+F+N+i,1+F+2*N+t,1);
        }
        addEdge(1+F+i,1+F+N+i,1);
    }
    int ans=maxFlow(1,n);
    printf("%d\n",ans);
    return 0;
}